package com.txc.pay.pay.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.txc.pay.config.WxPayConfig;
import com.txc.pay.entity.AccountEntity;
import com.txc.pay.enums.PayType;
import com.txc.pay.pay.ThirdPay;
import com.txc.pay.service.IAccountService;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.service.refund.RefundService;
import com.wechat.pay.java.service.refund.model.AmountReq;
import com.wechat.pay.java.service.refund.model.CreateRequest;
import com.wechat.pay.java.service.refund.model.QueryByOutRefundNoRequest;

import jakarta.annotation.Resource;

/**
 * @ClassName: WxPay
 * @Description: 微信支付抽象类
 * @Author: TXC
 * @Date: 2023-12-26 14:42
 **/
public abstract class WxPay implements ThirdPay {

    @Resource
    IAccountService accountService;

    /**
     * @param outRefundNo 商户退款订单号
     * @param refund      退款金额(单位为分)
     * @param total       原订单总金额（单位为分）
     * @return 结果
     */
    @Override
    public String refund(String outRefundNo, String refund, String total, String accountId) {
        RefundService service = new RefundService.Builder().config(rsaAutoCertificateConfig(accountId)).build();
        CreateRequest request = new CreateRequest();
        request.setOutRefundNo(outRefundNo);
        AmountReq amountReq = new AmountReq();
        // 设置退款金额（退款金额不可大于订单金额）单位为分
        try {
            amountReq.setRefund(Long.parseUnsignedLong(refund));
            // 订单总金额
            amountReq.setTotal(Long.parseUnsignedLong(total));
        } catch (NumberFormatException e) {
            throw new RuntimeException("金额需要是以分为单位的整数", e);
        }
        amountReq.setCurrency("CNY");
        amountReq.setFrom(null);
        request.setAmount(amountReq);
        return JSONUtil.parse(service.create(request)).toStringPretty();
    }

    public String queryByOutRefundNo(String outRefundNo, String accountId) {
        AccountEntity account = getAccount(accountId);
        RefundService service = new RefundService.Builder().config(rsaAutoCertificateConfig(accountId)).build();
        QueryByOutRefundNoRequest request = new QueryByOutRefundNoRequest();
        request.setOutRefundNo(outRefundNo);
        request.setSubMchid(wxPayConfig(account).getMerchantId());
        return JSONUtil.parse(service.queryByOutRefundNo(request)).toStringPretty();
    }

    /**
     * 初始化微信支付商户配置
     */

    public RSAAutoCertificateConfig rsaAutoCertificateConfig(String accountId) {
        AccountEntity account = getAccount(accountId);
        WxPayConfig wxPayConfig = wxPayConfig(account);
        assert wxPayConfig != null;
        return new RSAAutoCertificateConfig.Builder()
                .merchantId(wxPayConfig.getMerchantId())
                .privateKey(account.formatPrivateKey())
                .merchantSerialNumber(wxPayConfig.getMerchantSerialNumber())
                .apiV3Key(wxPayConfig.getApiV3Key())
                .build();
    }

    public WxPayConfig wxPayConfig(AccountEntity account) {
        try {
            return WxPayConfig.jsonToBean(account.getParam());
        } catch (Exception e) {
            throw new NullPointerException("请先配置微信支付参数");
        }
    }


    public AccountEntity getAccount(String accountId) {
        AccountEntity account;
        if (StrUtil.isNotEmpty(accountId)) {
            account = accountService.getById(accountId);
        } else {
            account = accountService.obtainDefaultAccount(PayType.WECHAT.getValue());
        }
        return account;
    }
}
